package com.grace.oss.service;

import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;

import com.grace.common.core.text.Convert;
import com.grace.common.enums.GraceServerRoot;
import com.grace.common.enums.GraceStorageRoot;
import com.grace.common.exception.ServiceException;
import com.grace.common.exception.file.FileNameLengthLimitExceededException;
import com.grace.common.exception.file.FileSizeLimitExceededException;
import com.grace.common.exception.file.InvalidExtensionException;
import com.grace.common.utils.StringUtils;
import com.grace.common.utils.file.FileUploadUtils;
import com.grace.oss.domain.OlyOss;
import com.grace.oss.properties.OssConfigProperties;
import com.grace.oss.utils.MimeExtensionEnum;
import com.grace.system.service.impl.SysSearchConfigServiceImpl;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.web.multipart.MultipartFile;

public interface OssHandler {

  /**
   * 缩略图宽
   */
  final static int THUMB_WIDTH = 256;

  /**
   * 缩略图高
   *
   */
  final static int THUMB_HEIGHT = 256;

  /**
   * 获取储存位置
   */
  String getOssType();

  /**
   * 文件上传
   * 
   * @param file
   * @param serverRoot
   * @return
   * @throws IOException
   * @throws FileSizeLimitExceededException
   * @throws InvalidExtensionException
   */
  OlyOss ossUpload(MultipartFile file, GraceStorageRoot serverRoot)
      throws IOException, FileSizeLimitExceededException, InvalidExtensionException;

  /**
   * 指定 文件上传路径 工作目录/文件上传根目录/key key唯一凭证
   * 
   * @param file     文件
   * @param rootPath 指定目录
   * @param fileName 文件名
   * @return
   * @throws IOException, FileSizeLimitExceededException,
   *                      InvalidExtensionException;
   */
  OlyOss ossAppointUpload(MultipartFile file, GraceServerRoot rootPath, String fileName, String[] allowedExtensio)
      throws IOException, FileSizeLimitExceededException, InvalidExtensionException;

  /**
   * 指定 文件上传路径 工作目录/文件上传根目录/key key唯一凭证
   * 
   * @param file     文件
   * @param rootPath 指定目录
   * @return
   * @throws IOException
   */
  OlyOss ossAppointUpload(MultipartFile file, GraceServerRoot rootPath, String[] allowedExtensio)
      throws IOException, FileSizeLimitExceededException, InvalidExtensionException;

  /**
   * 删除文件
   * 
   * @param filePath 删除的文件路径/key
   * @return
   */
  void ossDelete(String filePath);

  /**
   * 
   * @param fold 文件夹
   * @param file 文件
   * @param chan 是否中文转换
   * @return
   * @throws IOException
   */
  public static String getKey(String fold, MultipartFile file, boolean chan) throws IOException {
    return Paths.get(FilenameUtils.getBaseName(fold), FileUploadUtils.extractFilename(file, chan)).toString();
  }

  /**
   * 原文件名长度验证
   * 
   * @param fileName
   * @param maxLength
   * @throws FileNameLengthLimitExceededException
   */
  public static void fileNameLengthChick(String fileName, int maxLength) throws FileNameLengthLimitExceededException {
    int fileMaxlength = Objects.requireNonNull(fileName).length();
    if (fileMaxlength > maxLength) {
      throw new FileNameLengthLimitExceededException(maxLength);
    }
  }

  public static void check(MultipartFile file, SysSearchConfigServiceImpl configService)
      throws InvalidExtensionException {
    String fileName = FilenameUtils.getBaseName(file.getOriginalFilename());
    String groupName = OssConfigProperties.OSS_CONFIG_GROUP.defaultValue();
    // 验证文件名
    fileNameLengthChick(fileName, Integer.parseInt(
        configService.selectConfigDefaultValue(groupName, OssConfigProperties.OSS_FILE_NAME_MAX_LENGTH)));
    // 获取允许上传类型
    String gx = configService.selectConfigDefaultValue(groupName,
        OssConfigProperties.OSS_FILE_SUPPORT_TYPE);

    String[] supportType = StringUtils.isEmpty(gx) ? null : Convert.toStrArray(gx);
    String fileExtension = getFileTypeExtension(file, configService);
    if (ArrayUtils.isNotEmpty(supportType) && !ArrayUtils.contains(supportType, fileExtension)) {
      throw new ServiceException("上传文件不被允许");
    }
  }

  /**
   * 获取文件类型表达
   * 
   * @param suffix
   * @return
   */
  public static String getFileTypeExtension(MultipartFile file, SysSearchConfigServiceImpl configService) {
    String suffix = FileUploadUtils.getExtension(file);
    String groupName = OssConfigProperties.OSS_CONFIG_GROUP.defaultValue();
    if (ArrayUtils.contains(MimeExtensionEnum.IMAGE.getType(), suffix)) {
      if (Long.parseLong(configService.selectConfigDefaultValue(groupName,
          OssConfigProperties.OSS_IMAGE_MAX_SIZE)) * 1024 < file.getSize()) {
        throw new ServiceException("上传文件过大");
      }
      return MimeExtensionEnum.IMAGE.name().toLowerCase();
    } else if (ArrayUtils.contains(MimeExtensionEnum.DOCUMENT.getType(), suffix)) {
      if (Long.parseLong(configService.selectConfigDefaultValue(groupName,
          OssConfigProperties.OSS_DOCUMENT_MAX_SIZE)) * 1024 < file.getSize()) {
        throw new ServiceException("上传文件过大");
      }
      return MimeExtensionEnum.DOCUMENT.name().toLowerCase();
    } else if (ArrayUtils.contains(MimeExtensionEnum.COMPRESS.getType(), suffix)) {
      if (Long.parseLong(configService.selectConfigDefaultValue(groupName,
          OssConfigProperties.OSS_COMPRESS_MAX_SIZE)) * 1024 < file.getSize()) {
        throw new ServiceException("上传文件过大");
      }
      return MimeExtensionEnum.COMPRESS.name().toLowerCase();
    } else if (ArrayUtils.contains(MimeExtensionEnum.MUSIC.getType(), suffix)) {
      if (Long.parseLong(configService.selectConfigDefaultValue(groupName,
          OssConfigProperties.OSS_MUSIC_MAX_SIZE)) * 1024 < file.getSize()) {
        throw new ServiceException("上传文件过大");
      }
      return MimeExtensionEnum.MUSIC.name().toLowerCase();
    } else if (ArrayUtils.contains(MimeExtensionEnum.VIDEO.getType(), suffix)) {
      if (Long.parseLong(configService.selectConfigDefaultValue(groupName,
          OssConfigProperties.OSS_VIDEO_MAX_SIZE)) * 1024 < file.getSize()) {
        throw new ServiceException("上传文件过大");
      }
      return MimeExtensionEnum.VIDEO.name().toLowerCase();
    } else {
      return "file";
    }
  }

  public static String pathToUrl(String path) {
    return path.replace("\\", "/");
  }

}
